package values

import (
	"encoding/json"
	"errors"
	"fmt"
	"reflect"
	"slices"
	"strings"
	"time"
)

// SliceUnique 可比较切片去重
//   - 待处理切片为nil是返回nil,
//   - 待处理切片长度为0时, 返回空的 []T 切片
func SliceUnique[T comparable](sliceVal []T) []T {
	if sliceVal == nil {
		return nil
	}
	length := len(sliceVal)
	if length == 0 {
		return []T{}
	}
	result := make([]T, 0, length)
	uniqueVal := make(map[T]struct{}, length)
	for _, val := range sliceVal {
		if _, ok := uniqueVal[val]; !ok {
			result = append(result, val)
			uniqueVal[val] = struct{}{}
		}
	}
	return result
}

// ToSliceAny 转换any目标为 []any 切片, 如果转换失败, 则返回空的 []any 切片
func ToSliceAny(v any) []any {
	if v == nil {
		return []any{}
	}
	to, _ := ToSliceAnyE(v)
	return to
}

// ToSliceAnyD  转换any目标为 []any 切片, 如果转换失败, 则返回defaultVal指定的默认值
func ToSliceAnyD(v any, defaultVal []any) []any {
	if v == nil {
		return defaultVal
	}
	if to, err := ToSliceAnyE(v); err == nil {
		return to
	}
	return defaultVal
}

// ToSliceAnyE 转换any目标为 []any 切片, 如果转换失败, 则返回空的 []any 切片和错误信息
func ToSliceAnyE(v any) ([]any, error) {
	toVal := []any{}
	if v == nil {
		return toVal, errors.New("ToSliceAnyE: nil pointer not support")
	}
	// 通过断言判断是否为 []any / JsonString 类型
	switch vs := v.(type) {
	case []any:
		if len(vs) == 0 {
			return toVal, nil
		}
		return append(toVal, vs...), nil
	case *[]any:
		if len(*vs) == 0 {
			return toVal, nil
		}
		return append(toVal, *vs...), nil
	case string:
		if vs != "" && strings.HasPrefix(vs, "[") && strings.HasSuffix(vs, "]") && json.Valid([]byte(vs)) {
			vsAny := []any{}
			if err := json.Unmarshal([]byte(vs), &vsAny); err == nil {
				return vsAny, nil
			} else {
				return toVal, fmt.Errorf("ToSliceAnyE: string type to []T type, failed to unmarshal JSON: %s", err.Error())
			}
		}
		return toVal, errors.New("ToSliceAnyE: string type to []T type not support")
	case *string:
		if *vs != "" && strings.HasPrefix(*vs, "[") && strings.HasSuffix(*vs, "]") && json.Valid([]byte(*vs)) {
			vsAny := []any{}
			if err := json.Unmarshal([]byte(*vs), &vsAny); err == nil {
				return vsAny, nil
			} else {
				return toVal, fmt.Errorf("ToSliceAnyE: *string type to []T type, failed to unmarshal JSON: %s", err.Error())
			}
		}
		return toVal, errors.New("ToSliceAnyE: *string type to []T type not support")
	}
	// 如果待转换值是Golang 常用的基本类型或指针, 则直接返回错误信息
	if _isTypeBasic(v) {
		return toVal, errors.New("ToSliceAnyE: basic type to type []T not support")
	}
	// [1] 通过断言判断待转换值是否为[]TypeBase 类型
	if toVal, err, next := _appendSliceAnyBase(v); !next {
		return toVal, err
	}
	// [2] 通过断言判断待转换值是否为[][]TypeBase 类型
	if toVal, err, next := _appendSliceAnySlice(v); !next {
		return toVal, err
	}
	// [3] 通过断言判断待转换值是否为[]map[TypeBase]any 类型
	if toVal, err, next := _appendSliceAnyMap[string](v); !next {
		return toVal, err
	}
	if toVal, err, next := _appendSliceAnyMap[int](v); !next {
		return toVal, err
	}
	if toVal, err, next := _appendSliceAnyMap[uint](v); !next {
		return toVal, err
	}
	if toVal, err, next := _appendSliceAnyMap[int64](v); !next {
		return toVal, err
	}
	if toVal, err, next := _appendSliceAnyMap[uint64](v); !next {
		return toVal, err
	}
	if toVal, err, next := _appendSliceAnyMap[int32](v); !next {
		return toVal, err
	}
	if toVal, err, next := _appendSliceAnyMap[uint32](v); !next {
		return toVal, err
	}
	if toVal, err, next := _appendSliceAnyMap[int16](v); !next {
		return toVal, err
	}
	if toVal, err, next := _appendSliceAnyMap[uint16](v); !next {
		return toVal, err
	}
	if toVal, err, next := _appendSliceAnyMap[int8](v); !next {
		return toVal, err
	}
	if toVal, err, next := _appendSliceAnyMap[uint8](v); !next {
		return toVal, err
	}
	if toVal, err, next := _appendSliceAnyMap[float64](v); !next {
		return toVal, err
	}
	if toVal, err, next := _appendSliceAnyMap[float32](v); !next {
		return toVal, err
	}
	if toVal, err, next := _appendSliceAnyMap[time.Time](v); !next {
		return toVal, err
	}
	if toVal, err, next := _appendSliceAnyMap[time.Duration](v); !next {
		return toVal, err
	}
	if toVal, err, next := _appendSliceAnyMap[time.Month](v); !next {
		return toVal, err
	}
	if toVal, err, next := _appendSliceAnyMap[time.Weekday](v); !next {
		return toVal, err
	}
	if toVal, err, next := _appendSliceAnyMap[bool](v); !next {
		return toVal, err
	}

	// [4] 尝试反射检查是否为Slice或Array类型
	return _appendSliceAnyReflect(v)
}
func _appendSliceAny[T any](vs []T) ([]any, error, bool) {
	if vs == nil {
		return []any{}, errors.New("ToSliceAnyE: nil pointer not support"), false // Next "false" To Break
	}
	if len(vs) == 0 {
		return []any{}, nil, false // Next "false" To Break
	}
	toVal := make([]any, len(vs))
	for i, v := range vs {
		toVal[i] = v
	}
	return toVal, nil, false // Next "false" To Break
}

// [1] 通过断言判断待转换值是否为[]TypeBase 类型
func _appendSliceAnyBase(v any) ([]any, error, bool) {
	switch vs := v.(type) {
	default:
		return []any{}, nil, true // Next "true" To continue
	case []any:
		return slices.Clone(vs), nil, false // Next "false" To Break
	case *[]any:
		return slices.Clone(*vs), nil, false // Next "false" To Break
	case []string:
		return _appendSliceAny(vs)
	case *[]string:
		return _appendSliceAny(*vs)
	case []*string:
		return _appendSliceAny(vs)
	case []int:
		return _appendSliceAny(vs)
	case *[]int:
		return _appendSliceAny(*vs)
	case []*int:
		return _appendSliceAny(vs)
	case []int8:
		return _appendSliceAny(vs)
	case *[]int8:
		return _appendSliceAny(*vs)
	case []*int8:
		return _appendSliceAny(vs)
	case []int16:
		return _appendSliceAny(vs)
	case *[]int16:
		return _appendSliceAny(*vs)
	case []*int16:
		return _appendSliceAny(vs)
	case []int32:
		return _appendSliceAny(vs)
	case *[]int32:
		return _appendSliceAny(*vs)
	case []*int32:
		return _appendSliceAny(vs)
	case []int64:
		return _appendSliceAny(vs)
	case *[]int64:
		return _appendSliceAny(*vs)
	case []*int64:
		return _appendSliceAny(vs)
	case []uint8:
		return _appendSliceAny(vs)
	case *[]uint8:
		return _appendSliceAny(*vs)
	case []*uint8:
		return _appendSliceAny(vs)
	case []uint16:
		return _appendSliceAny(vs)
	case *[]uint16:
		return _appendSliceAny(*vs)
	case []*uint16:
		return _appendSliceAny(vs)
	case []uint32:
		return _appendSliceAny(vs)
	case *[]uint32:
		return _appendSliceAny(*vs)
	case []*uint32:
		return _appendSliceAny(vs)
	case []uint64:
		return _appendSliceAny(vs)
	case *[]uint64:
		return _appendSliceAny(*vs)
	case []*uint64:
		return _appendSliceAny(vs)
	case []float32:
		return _appendSliceAny(vs)
	case *[]float32:
		return _appendSliceAny(*vs)
	case []*float32:
		return _appendSliceAny(vs)
	case []float64:
		return _appendSliceAny(vs)
	case *[]float64:
		return _appendSliceAny(*vs)
	case []*float64:
		return _appendSliceAny(vs)
	case []bool:
		return _appendSliceAny(vs)
	case *[]bool:
		return _appendSliceAny(*vs)
	case []*bool:
		return _appendSliceAny(vs)
	case []time.Time:
		return _appendSliceAny(vs)
	case *[]time.Time:
		return _appendSliceAny(*vs)
	case []*time.Time:
		return _appendSliceAny(vs)
	case []time.Duration:
		return _appendSliceAny(vs)
	case *[]time.Duration:
		return _appendSliceAny(*vs)
	case []*time.Duration:
		return _appendSliceAny(vs)
	case []json.Number:
		return _appendSliceAny(vs)
	case *[]json.Number:
		return _appendSliceAny(*vs)
	case []*json.Number:
		return _appendSliceAny(vs)
	case []error:
		return _appendSliceAny(vs)
	case *[]error:
		return _appendSliceAny(*vs)
	case []*error:
		return _appendSliceAny(vs)
	}
}

// [2] 通过断言判断待转换值是否为[][]TypeBase 类型
func _appendSliceAnySlice(v any) ([]any, error, bool) {
	switch vs := v.(type) {
	default:
		return []any{}, nil, true // Next "true" To continue
	case [][]any:
		return _appendSliceAny(vs)
	case *[][]any:
		return _appendSliceAny(*vs)
	case [][]string:
		return _appendSliceAny(vs)
	case *[][]string:
		return _appendSliceAny(*vs)
	case [][]int:
		return _appendSliceAny(vs)
	case *[][]int:
		return _appendSliceAny(*vs)
	case [][]int8:
		return _appendSliceAny(vs)
	case *[][]int8:
		return _appendSliceAny(*vs)
	case [][]int16:
		return _appendSliceAny(vs)
	case *[][]int16:
		return _appendSliceAny(*vs)
	case [][]int32:
		return _appendSliceAny(vs)
	case *[][]int32:
		return _appendSliceAny(*vs)
	case [][]int64:
		return _appendSliceAny(vs)
	case *[][]int64:
		return _appendSliceAny(*vs)
	case [][]uint8:
		return _appendSliceAny(vs)
	case *[][]uint8:
		return _appendSliceAny(*vs)
	case [][]uint16:
		return _appendSliceAny(vs)
	case *[][]uint16:
		return _appendSliceAny(*vs)
	case [][]uint32:
		return _appendSliceAny(vs)
	case *[][]uint32:
		return _appendSliceAny(*vs)
	case [][]uint64:
		return _appendSliceAny(vs)
	case *[][]uint64:
		return _appendSliceAny(*vs)
	case [][]float32:
		return _appendSliceAny(vs)
	case *[][]float32:
		return _appendSliceAny(*vs)
	case [][]float64:
		return _appendSliceAny(vs)
	case *[][]float64:
		return _appendSliceAny(*vs)
	case [][]bool:
		return _appendSliceAny(vs)
	case *[][]bool:
		return _appendSliceAny(*vs)
	case [][]time.Time:
		return _appendSliceAny(vs)
	case *[][]time.Time:
		return _appendSliceAny(*vs)
	case [][]time.Duration:
		return _appendSliceAny(vs)
	case *[][]time.Duration:
		return _appendSliceAny(*vs)
	case [][]time.Month:
		return _appendSliceAny(vs)
	case *[][]time.Month:
		return _appendSliceAny(*vs)
	case [][]time.Weekday:
		return _appendSliceAny(vs)
	case *[][]time.Weekday:
		return _appendSliceAny(*vs)
	case [][]json.Number:
		return _appendSliceAny(vs)
	case *[][]json.Number:
		return _appendSliceAny(*vs)
	case [][]error:
		return _appendSliceAny(vs)
	case *[][]error:
		return _appendSliceAny(*vs)
	}
}

// [3] 通过断言判断待转换值是否为[]map[TypeBase]any 类型
func _appendSliceAnyMap[K TypeBase](v any) ([]any, error, bool) {
	switch vs := v.(type) {
	default:
		return []any{}, nil, true // Next "true" To continue
	case []TypeMapAny[K]:
		return _appendSliceAny(vs)
	case []TypeMapBase[K, string]:
		return _appendSliceAny(vs)
	case *[]TypeMapBase[K, string]:
		return _appendSliceAny(*vs)
	case []TypeMapBase[K, bool]:
		return _appendSliceAny(vs)
	case *[]TypeMapBase[K, bool]:
		return _appendSliceAny(*vs)
	case []TypeMapBase[K, int]:
		return _appendSliceAny(vs)
	case *[]TypeMapBase[K, int]:
		return _appendSliceAny(*vs)
	case []TypeMapBase[K, int8]:
		return _appendSliceAny(vs)
	case *[]TypeMapBase[K, int8]:
		return _appendSliceAny(*vs)
	case []TypeMapBase[K, int16]:
		return _appendSliceAny(vs)
	case *[]TypeMapBase[K, int16]:
		return _appendSliceAny(*vs)
	case []TypeMapBase[K, int32]:
		return _appendSliceAny(vs)
	case *[]TypeMapBase[K, int32]:
		return _appendSliceAny(*vs)
	case []TypeMapBase[K, int64]:
		return _appendSliceAny(vs)
	case *[]TypeMapBase[K, int64]:
		return _appendSliceAny(*vs)
	case []TypeMapBase[K, uint8]:
		return _appendSliceAny(vs)
	case *[]TypeMapBase[K, uint8]:
		return _appendSliceAny(*vs)
	case []TypeMapBase[K, uint16]:
		return _appendSliceAny(vs)
	case *[]TypeMapBase[K, uint16]:
		return _appendSliceAny(*vs)
	case []TypeMapBase[K, uint32]:
		return _appendSliceAny(vs)
	case *[]TypeMapBase[K, uint32]:
		return _appendSliceAny(*vs)
	case []TypeMapBase[K, uint64]:
		return _appendSliceAny(vs)
	case *[]TypeMapBase[K, uint64]:
		return _appendSliceAny(*vs)
	case []TypeMapBase[K, float32]:
		return _appendSliceAny(vs)
	case *[]TypeMapBase[K, float32]:
		return _appendSliceAny(*vs)
	case []TypeMapBase[K, float64]:
		return _appendSliceAny(vs)
	case *[]TypeMapBase[K, float64]:
		return _appendSliceAny(*vs)
	case []TypeMapBase[K, time.Time]:
		return _appendSliceAny(vs)
	case *[]TypeMapBase[K, time.Time]:
		return _appendSliceAny(*vs)
	case []TypeMapBase[K, time.Duration]:
		return _appendSliceAny(vs)
	case *[]TypeMapBase[K, time.Duration]:
		return _appendSliceAny(*vs)
	case []TypeMapBase[K, time.Month]:
		return _appendSliceAny(vs)
	case *[]TypeMapBase[K, time.Month]:
		return _appendSliceAny(*vs)
	case []TypeMapBase[K, time.Weekday]:
		return _appendSliceAny(vs)
	case *[]TypeMapBase[K, time.Weekday]:
		return _appendSliceAny(*vs)
	}
}

// [4] 尝试反射检查是否为Slice或Array类型
func _appendSliceAnyReflect(v any) ([]any, error) {
	toVal := []any{}
	// 获取输入值的反射类型和值
	vType := reflect.TypeOf(v)
	vValue := reflect.ValueOf(v)
	if vType.Kind() == reflect.Ptr {
		if vValue.IsNil() {
			return toVal, errors.New("ToSliceAnyE: input is a nil pointer")
		}
		vType = vType.Elem()
		vValue = vValue.Elem()
	}
	// 检查是否为切片或数组类型
	if vType.Kind() != reflect.Slice && vType.Kind() != reflect.Array {
		return toVal, fmt.Errorf("ToSliceAnyE: unsupported type %T, expected slice or array", v)
	}
	// 如果长度为0，直接返回空切片
	if vValue.Len() == 0 {
		return toVal, nil
	}
	toVal = make([]any, vValue.Len())
	for i := range vValue.Len() {
		toVal[i] = vValue.Index(i).Interface()
	}
	return toVal, nil
}
